/*
 * Copyright (c) 2024 iSOFT INFRASTRUCTURE SOFTWARE CO., LTD.
 * easyAda is licensed under Mulan PubL v2.
 * You can use this software according to the terms and conditions of the Mulan PubL v2.
 * You may obtain a copy of Mulan PubL v2 at:
 *          http://license.coscl.org.cn/MulanPubL-2.0
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PubL v2 for more details.
 */

#include <caps/cnode.h>
#include <core/schedule.h>
#include <caps/cond.h>
#include <caps/mutex.h>
#include <uapi/errors.h>
#include <uapi/ipcops.h>

static inline void cap_cond_set_obj(capability_t *cap, cond_t *obj)
{
    cap_set_long_info(cap, (unsigned long)obj);
}

void cap_cond_init(capability_t *cap, cond_t *obj)
{
    cond_get(obj);
    cap_basic_init(cap, CAP_COND);
    cap_cond_set_obj(cap, obj);
}

void cap_cond_dispatcher(capability_t *cap, unsigned long tag, unsigned long m0, unsigned long m1, unsigned long m2,
                          unsigned long m3, unsigned long m4, unsigned long m5)
{
    mutex_t      *mutex = NULL;
    cptr_t        mutex_cptr;
    capability_t *cap_mutex;
    cond_t *cond = cap_cond_get_obj(cap);

    switch (msgtag_get_op(tag)) {
        case CAP_COND_OP_TIMED_WAIT:
            mutex_cptr = m0;
	    if (mutex_cptr != 0) {
                cap_mutex = cnode_cptr_lookup(task_get_cnode(current()), mutex_cptr, sizeof(unsigned long) * 8U);
                mutex     = (mutex_t*)cap_mutex_get_obj(cap_mutex);
            }

	    task_set_retcode(current(), cond_timewait(cond, mutex, m1));
            break;

        case CAP_COND_OP_SIGNAL:
            task_set_retcode(current(), cond_signal(cond));
            break;

        case CAP_COND_OP_BROADCAST:
	    task_set_retcode(current(), cond_broadcast(cond));
            break;

        case CAP_COND_OP_DESTROY:
	    task_set_retcode(current(), cond_destroy(cond));
	    break;

        default:
            task_set_retcode(current(), ERR_TO_RETCODE(-ENOSYS));
            break;
    }
}
